#include "stdafx.h"
#include "cz_string.h"

// the value of "flag" in "cz_string_in_uToX" function
#define CZ_STRING_IN_8					0x00010000
#define CZ_STRING_IN_16					0x00020000
#define CZ_STRING_IN_32					0x00040000
#define CZ_STRING_IN_SIGNED				0x00080000

wstring cz_string_in_64ToW(IN u64 v, IN u32 flag);
string cz_string_in_64ToA(IN u64 v, IN u32 flag);

wstring cz_string_in_32ToW(IN u32 v, IN u32 flag);
string cz_string_in_32ToA(IN u32 v, IN u32 flag);




/* SplitX_v1 -----------------------------------------------------------------------------------------------*/
bool cz_string_SplitW_v1(IN wstringc& wcsSrc, IN wstringc& wcsDelimiters, OUT vector<wstring >& vctDst)
{
	wstring::size_type pos1, pos2;
	pos2 = 0;
	while(true)
	{
		pos1 = wcsSrc.find_first_not_of(wcsDelimiters, pos2);
		if (pos1 == wstring::npos) break;
		pos2 = wcsSrc.find_first_of(wcsDelimiters, pos1 + 1);
		if (pos2 == wstring::npos)
		{
			vctDst.push_back(wcsSrc.substr(pos1));
			break;
		}
		vctDst.push_back(wcsSrc.substr(pos1, pos2 - pos1));
		++pos2;
	}
	return true;
}

bool cz_string_SplitA_v1(IN stringc& strSrc, IN stringc& strDelimiters, OUT vector<string >& vctDst)
{
	string::size_type pos1, pos2;
	pos2 = 0;
	while(true)
	{
		pos1 = strSrc.find_first_not_of(strDelimiters, pos2);
		if (pos1 == string::npos) break;
		pos2 = strSrc.find_first_of(strDelimiters, pos1 + 1);
		if (pos2 == string::npos)
		{
			vctDst.push_back(strSrc.substr(pos1));
			break;
		}
		vctDst.push_back(strSrc.substr(pos1, pos2 - pos1));
		++pos2;
	}
	return true;
}

/* SplitX_v2 -----------------------------------------------------------------------------------------------*/
bool cz_string_SplitW_v2(IN wstringc& wcsSrc, IN wstringc& wcsDelimiters, OUT vector<wstring >& vctDst)
{
	wstring::size_type pos1, pos2;
	pos1 = 0;
	while(true)
	{
		pos2 = wcsSrc.find_first_of(wcsDelimiters, pos1);
		if (pos2 == wstring::npos)
		{
			vctDst.push_back(wcsSrc.substr(pos1));
			break;
		}
		vctDst.push_back(wcsSrc.substr(pos1, pos2 - pos1));
		pos1 = pos2 + 1;
	}
	return true;
}

bool cz_string_SplitA_v2(IN stringc& strSrc, IN stringc& strDelimiters, OUT vector<string >& vctDst)
{
	string::size_type pos1, pos2;
	pos1 = 0;
	while(true)
	{
		pos2 = strSrc.find_first_of(strDelimiters, pos1);
		if (pos2 == string::npos)
		{
			vctDst.push_back(strSrc.substr(pos1));
			break;
		}
		vctDst.push_back(strSrc.substr(pos1, pos2 - pos1));
		pos1 = pos2 + 1;
	}
	return true;
}

/* SplitX_v3 -----------------------------------------------------------------------------------------------*/
bool cz_string_SplitW_v3(IN wstringc& wcsSrc, IN wstringc& wcsDelimiters, OUT vector<wstring >& vctDst)
{
	wstring::size_type pos1, pos2 = 0;

	//wcsDlimit could not contain quote(")
	for (pos1 = 0; pos1 < wcsDelimiters.size(); ++pos1)
	{
		if (wcsDelimiters[pos1] == L'\"')
		{
			CZ_LOG_ERRORW(L"");		// parameter 2 is invalid
			return false;
		}
	}

	while(true)
	{
		pos1 = wcsSrc.find_first_not_of(wcsDelimiters, pos2);
		if (pos1 == wstring::npos) break;
		if (wcsSrc[pos1] == L'\"')
		{
			pos2 = wcsSrc.find_first_of(L'\"', pos1 + 1);
			if (pos2 == wstring::npos)
			{
				CZ_LOG_ERRORW(L"");		// parameter 1 is invalid
				return false;
			}
			//do not ignore ""
			vctDst.push_back(wcsSrc.substr(pos1 + 1, pos2 - pos1 - 1));
			++pos2;
		}
		else
		{
			//deal with the situation like 123"456"
			pos2 = wcsSrc.find_first_of(wcsDelimiters + L'\"', pos1 + 1);
			if (pos2 == wstring::npos)
			{
				vctDst.push_back(wcsSrc.substr(pos1));
				break;
			}
			vctDst.push_back(wcsSrc.substr(pos1, pos2 - pos1));
		}
	}
	return true;
}

bool cz_string_SplitA_v3(IN stringc& strSrc, IN stringc& strDelimiters, OUT vector<string >& vctDst)
{
	string::size_type pos1, pos2 = 0;

	//strDlimit could not contain quote(")
	for (pos1 = 0; pos1 < strDelimiters.size(); ++pos1)
	{
		if (strDelimiters[pos1] == '\"')
		{
			CZ_LOG_ERRORA("");			// parameter 2 is invalid
			return false;
		}
	}

	while(true)
	{
		pos1 = strSrc.find_first_not_of(strDelimiters, pos2);
		if (pos1 == string::npos) break;
		if (strSrc[pos1] == '\"')
		{
			pos2 = strSrc.find_first_of('\"', pos1 + 1);
			if (pos2 == string::npos)
			{
				CZ_LOG_ERRORA("");		// "parameter 1 is invalid"
				return false;
			}
			//do not ignore ""
			vctDst.push_back(strSrc.substr(pos1 + 1, pos2 - pos1 - 1));
			++pos2;
		}
		else
		{
			//deal with the situation like 123"456"
			pos2 = strSrc.find_first_of(strDelimiters + '\"', pos1 + 1);
			if (pos2 == string::npos)
			{
				vctDst.push_back(strSrc.substr(pos1));
				break;
			}
			vctDst.push_back(strSrc.substr(pos1, pos2 - pos1));
		}
	}
	return true;
}

/* TrimLeftX -----------------------------------------------------------------------------------------------*/
wstring cz_string_TrimLeftW(IN wstringc& wcs, IN wstringc& wcsIgnorCharacters)
{
	return wcs.substr(wcs.find_first_not_of(wcsIgnorCharacters));
}

string cz_string_TrimLeftA(IN stringc& str, IN stringc& strIgnorCharacters)
{
	return str.substr(str.find_first_not_of(strIgnorCharacters));
}

/* TrimRightX -----------------------------------------------------------------------------------------------*/
wstring cz_string_TrimRightW(IN wstringc& wcs, IN wstringc& wcsIgnorCharacters)
{
	return wcs.substr(0, wcs.find_last_not_of(wcsIgnorCharacters) + 1);
}

string cz_string_TrimRightA(IN stringc& str, IN stringc& strIgnorCharacters)
{
	return str.substr(0, str.find_last_not_of(strIgnorCharacters) + 1);
}

/* TrimRightX -----------------------------------------------------------------------------------------------*/
wstring cz_string_TrimW(IN wstringc& wcs, IN wstringc& wcsIgnorCharacters)
{
	u32 p1, p2;
	p1 = wcs.find_first_not_of(wcsIgnorCharacters);
	if (p1 == wstring::npos) return L"";
	p2 = wcs.find_last_not_of(wcsIgnorCharacters);
	if (p2 == wstring::npos) return L"";
	return wcs.substr(p1, p2 - p1 + 1);
}

string cz_string_TrimA(IN stringc& str, IN stringc& strIgnorCharacters)
{
	u32 p1, p2;
	p1 = str.find_first_not_of(strIgnorCharacters);
	if (p1 == string::npos) return "";
	p2 = str.find_last_not_of(strIgnorCharacters);
	if (p2 == string::npos) return "";
	return str.substr(p1, p2 - p1 + 1);
}

/* GetLeftX ------------------------------------------------------------------------------------------------*/
wstring cz_string_GetLeftW(IN wstringc& wcs, IN wchar wcDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = wcs.find(wcDelimiter);
	if (p == wstring::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? L"" : wcs);
	return wcs.substr(0, p + (((flag & CZ_STRING_INCLUDE) != 0) ? 1 : 0));
}

string cz_string_GetLeftA(IN stringc& str, IN char cDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = str.find(cDelimiter);
	if (p == string::npos) return (((flag & CZ_STRING_EMPTY ) != 0) ? "" : str);
	return str.substr(0, p + (((flag & CZ_STRING_INCLUDE) != 0) ? 1 : 0));
}

/* GetRightX -----------------------------------------------------------------------------------------------*/
wstring cz_string_GetRightW(IN wstringc& wcs, IN wchar wcDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = wcs.find(wcDelimiter);
	if (p == wstring::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? L"" : wcs);
	return wcs.substr(p + (((flag & CZ_STRING_INCLUDE) != 0) ? 0 : 1));
}

string cz_string_GetRightA(IN stringc& str, IN char cDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = str.find(cDelimiter);
	if (p == string::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? "" : str);
	return str.substr(p + (((flag & CZ_STRING_INCLUDE) != 0) ? 0 : 1));
}

/* ReverseGetLeftX -----------------------------------------------------------------------------------------*/
wstring cz_string_ReverseGetLeftW(IN wstringc& wcs, IN wchar wcDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = wcs.rfind(wcDelimiter);
	if (p == wstring::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? L"" : wcs);
	return wcs.substr(0, p + (((flag & CZ_STRING_INCLUDE) != 0) ? 1 : 0));
}

string cz_string_ReverseGetLeftA(IN stringc& str, IN char cDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = str.rfind(cDelimiter);
	if (p == string::npos) return (((flag & CZ_STRING_EMPTY ) != 0) ? "" : str);
	return str.substr(0, p + (((flag & CZ_STRING_INCLUDE) != 0) ? 1 : 0));
}

/* ReverseGetRightX ----------------------------------------------------------------------------------------*/
wstring cz_string_ReverseGetRightW(IN wstringc& wcs, IN wchar wcDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = wcs.rfind(wcDelimiter);
	if (p == wstring::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? L"" : wcs);
	return wcs.substr(p + (((flag & CZ_STRING_INCLUDE) != 0) ? 0 : 1));
}

string cz_string_ReverseGetRightA(IN stringc& str, IN char cDelimiter, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 p = str.rfind(cDelimiter);
	if (p == string::npos) return (((flag & CZ_STRING_EMPTY) != 0) ? "" : str);
	return str.substr(p + (((flag & CZ_STRING_INCLUDE) != 0) ? 0 : 1));
}

/* 2LowerX -------------------------------------------------------------------------------------------------*/
wstring cz_string_ToLowerW(IN wstringc& wcs)
{
	wstring wcsTemp;
	wcsTemp.resize(wcs.size());
	transform(wcs.begin(), wcs.end(), wcsTemp.begin(), tolower);
	return wcsTemp;
}

string cz_string_ToLowerA(IN stringc& str)
{
	string strTemp;
	strTemp.resize(str.size());
	transform(str.begin(), str.end(), strTemp.begin(), tolower);
	return strTemp;
}

/* 2UpperX -------------------------------------------------------------------------------------------------*/
wstring cz_string_ToUpperW(IN wstringc& wcs)
{
	wstring wcsTemp;
	wcsTemp.resize(wcs.size());
	transform(wcs.begin(), wcs.end(), wcsTemp.begin(), toupper);
	return wcsTemp;
}

string cz_string_ToUpperA(IN stringc& str)
{
	string strTemp;
	strTemp.resize(str.size());
	transform(str.begin(), str.end(), strTemp.begin(), toupper);
	return strTemp;
}

// u64ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_U64ToW(IN u64 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_64ToW(v, flag);
}

string cz_string_U64ToA(IN u64 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_64ToA(v, flag);
}

/* u32ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_U32ToW(IN u32 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_32);
}

string cz_string_U32ToA(IN u32 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_32);
}

/* u16ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_U16ToW(IN u16 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_16);
}

string cz_string_U16ToA(IN u16 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_16);
}

/* u8ToX ---------------------------------------------------------------------------------------------------*/
wstring cz_string_U8ToW(IN u8 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_8);
}

string cz_string_U8ToA(IN u8 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_8);
}

/* i64ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_I64ToW(IN i64 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_64ToW(v, flag | CZ_STRING_IN_SIGNED);
}

string cz_string_I64ToA(IN i64 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_64ToA(v, flag | CZ_STRING_IN_SIGNED);
}

/* i32ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_I32ToW(IN i32 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_32);
}

string cz_string_I32ToA(IN i32 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_32);
}

/* i16ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_I16ToW(IN i16 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_16);
}

string cz_string_I16ToA(IN i16 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_16);
}

/* i8ToX --------------------------------------------------------------------------------------------------*/
wstring cz_string_I8ToW(IN i8 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToW(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_8);
}

string cz_string_I8ToA(IN i8 v, IN u32 flag /* = CZ_STRING_NULL */)
{
	return cz_string_in_32ToA(v, flag | CZ_STRING_IN_SIGNED | CZ_STRING_IN_8);
}

/* XTou64 --------------------------------------------------------------------------------------------------*/
u64 cz_string_WToU64(IN wstringc& wcs, IN u32 flag /* = CZ_STRING_NULL */)
{
	u64 value;
	wstring wcsFormat = L"%I64";
	if ((flag & CZ_STRING_HEX) != 0) wcsFormat += L"x";
	else if ((flag & CZ_STRING_OCT) != 0) wcsFormat += L"o";
	else wcsFormat += L"u";
	swscanf_s(wcs.c_str(), wcsFormat.c_str(), &value);
	return value;
}

u64 cz_string_AToU64(IN stringc& str, IN u32 flag /* = CZ_STRING_NULL */)
{
	u64 value;
	string strFormat = "%I64";
	if ((flag & CZ_STRING_HEX) != 0) strFormat += "x";
	else if ((flag & CZ_STRING_OCT) != 0) strFormat += "o";
	else strFormat += "u";
	sscanf_s(str.c_str(), strFormat.c_str(), &value);
	return value;
}

/* XTou32 --------------------------------------------------------------------------------------------------*/
u32 cz_string_WToU32(IN wstringc& wcs, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 value;
	wstring wcsFormat = L"%";
	if ((flag & CZ_STRING_HEX) != 0) wcsFormat += L"x";
	else if ((flag & CZ_STRING_OCT) != 0) wcsFormat += L"o";
	else wcsFormat += L"u";
	swscanf_s(wcs.c_str(), wcsFormat.c_str(), &value);
	return value;
}

u32 cz_string_AToU32(IN stringc& str, IN u32 flag /* = CZ_STRING_NULL */)
{
	u32 value;
	string strFormat = "%";
	if ((flag & CZ_STRING_HEX) != 0) strFormat += "x";
	else if ((flag & CZ_STRING_OCT) != 0) strFormat += "o";
	else strFormat += "u";
	sscanf_s(str.c_str(), strFormat.c_str(), &value);
	return value;
}

/* IsViaibleX ----------------------------------------------------------------------------------------------*/
bool cz_string_IsVisibleW(IN wchar wc)
{
	return (static_cast<u16 >(wc) >= 0x20) && (static_cast<u16 >(wc) <= 0x7E);
}

bool cz_string_IsVisibleA(IN char c)
{
	return (static_cast<u8 >(c) >= 0x20) && (static_cast<u8 >(c) <= 0x7E);
}




//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* 64ToX ----------------------------------------------------------------------------------------------------*/
wstring cz_string_in_64ToW(IN u64 v, IN u32 flag)
{
	wchar p[32];
	wstring wcsFormat = L"";

	if (((i64)v < 0) && ((flag & CZ_STRING_IN_SIGNED) != 0))
	{
		wcsFormat += L"-";
		v = 0 - v;
	}

	if ((flag & CZ_STRING_PREFIX) != 0)
	{
		if ((flag & CZ_STRING_HEX) != 0)
		{
			if ((flag & CZ_STRING_UPPER_CASE) != 0) wcsFormat += L"0X";
			else wcsFormat += L"0x";
		}
		else if ((flag & CZ_STRING_OCT) != 0)
		{
			wcsFormat += L"0";
		}
	}
	wcsFormat += L"%";

	if (((flag & CZ_STRING_FILL) !=0) && ((flag & CZ_STRING_HEX) != 0))
	{
		wcsFormat += L"016";
	}

	wcsFormat += L"I64";

	if ((flag & CZ_STRING_HEX) != 0)
	{
		if ((flag & CZ_STRING_UPPER_CASE) != 0) wcsFormat += L"X";
		else wcsFormat += L"x";
	}
	else if ((flag & CZ_STRING_OCT) != 0) wcsFormat += L"o";
	else wcsFormat += L"u";

	_snwprintf_s(p, 32, wcsFormat.c_str(), v);

	return p;
}

string cz_string_in_64ToA(IN u64 v, IN u32 flag)
{
	char p[32];
	string strFormat = "";

	if (((i64)v < 0) && ((flag & CZ_STRING_IN_SIGNED) != 0))
	{
		strFormat += "-";
		v = 0 - v;
	}

	if ((flag & CZ_STRING_PREFIX) != 0)
	{
		if ((flag & CZ_STRING_HEX) != 0)
		{
			if ((flag & CZ_STRING_UPPER_CASE) != 0) strFormat += "0X";
			else strFormat += "0x";
		}
		else if ((flag & CZ_STRING_OCT) != 0)
		{
			strFormat += "0";
		}
	}
	strFormat += "%";

	if (((flag & CZ_STRING_FILL) !=0) && ((flag & CZ_STRING_HEX) != 0))
	{
		strFormat += "016";
	}

	strFormat += "I64";

	if ((flag & CZ_STRING_HEX) != 0)
	{
		if ((flag & CZ_STRING_UPPER_CASE) != 0) strFormat += "X";
		else strFormat += "x";
	}
	else if ((flag & CZ_STRING_OCT) != 0) strFormat += "o";
	else strFormat += "u";

	_snprintf_s(p, 32, strFormat.c_str(), v);

	return p;
}

/* 32ToX ----------------------------------------------------------------------------------------------------*/
wstring cz_string_in_32ToW(IN u32 v, IN u32 flag)
{
	wchar p[32];
	wstring wcsFormat = L"";

	if (((i32)v < 0) && ((flag & CZ_STRING_IN_SIGNED) != 0))
	{
		wcsFormat += L"-";
		v = 0 - v;
	}

	if ((flag & CZ_STRING_PREFIX) != 0)
	{
		if ((flag & CZ_STRING_HEX) != 0)
		{
			if ((flag & CZ_STRING_UPPER_CASE) != 0) wcsFormat += L"0X";
			else wcsFormat += L"0x";
		}
		else if ((flag & CZ_STRING_OCT) != 0)
		{
			wcsFormat += L"0";
		}
	}

	wcsFormat += L"%";

	if (((flag & CZ_STRING_FILL) != 0) && ((flag & CZ_STRING_HEX) != 0))
	{
		if ((flag & CZ_STRING_IN_8) != 0) wcsFormat += L"02";
		else if ((flag & CZ_STRING_IN_16) != 0) wcsFormat += L"04";
		else wcsFormat += L"08";
	}

	if ((flag & CZ_STRING_HEX) != 0)
	{
		if ((flag & CZ_STRING_UPPER_CASE) != 0) wcsFormat += L"X";
		else wcsFormat += L"x";
	}
	else if ((flag & CZ_STRING_OCT) != 0) wcsFormat += L"o";
	else wcsFormat += L"u";

	_snwprintf_s(p, 32, wcsFormat.c_str(), v);

	return p;
}

string cz_string_in_32ToA(IN u32 v, IN u32 flag)
{
	char p[32];
	string strFormat = "";

	if (((i32)v < 0) && ((flag & CZ_STRING_IN_SIGNED) != 0))
	{
		strFormat += "-";
		v = 0 - v;
	}

	if ((flag & CZ_STRING_PREFIX) != 0)
	{
		if ((flag & CZ_STRING_HEX) != 0)
		{
			if ((flag & CZ_STRING_UPPER_CASE) != 0) strFormat += "0X";
			else strFormat += "0x";
		}
		else if ((flag & CZ_STRING_OCT) != 0)
		{
			strFormat += "0";
		}
	}

	strFormat += "%";

	if (((flag & CZ_STRING_FILL) != 0) && ((flag & CZ_STRING_HEX) != 0))
	{
		if ((flag & CZ_STRING_IN_8) != 0) strFormat += "02";
		else if ((flag & CZ_STRING_IN_16) != 0) strFormat += "04";
		else strFormat += "08";
	}

	if ((flag & CZ_STRING_HEX) != 0)
	{
		if ((flag & CZ_STRING_UPPER_CASE) != 0) strFormat += "X";
		else strFormat += "x";
	}
	else if ((flag & CZ_STRING_OCT) != 0) strFormat += "o";
	else strFormat += "u";

	_snprintf_s(p, 32, strFormat.c_str(), v);

	return p;
}